package OddMuse;

=head1 NAME

OddMuse::Searching::Engine - Provides search engine html for OddMuse Searches

=head1 DESCRIPTION

This page renders search results returned from 
OddMuse::Searching->new('searchterm') into html.

=head1 DEPENDENCIES

L<OddMuse::Searching>, L<OddMuse::Date>

=cut

$VERSION = ( q$Revision: 30 $ ) =~ /(\d+)/g;
use OddMuse::Searching;
use OddMuse::Date;
use strict;

=head1 SYNOPSIS

Functions only within the OddMuse Namespace.  OddMuse Functions are typically
not OO, and they are called directly by name, action, or inserted into a rule.

=head1 FUNCTIONS

=over 4

=item * MetaSearch

This prints a search result page with grouped results.  For example, pages
which were matched in the WikiName are returned first, followed by matches in
the Smart title and so on.

=cut

sub MetaSearch {
    my ( $resultcount, @uriresult, @titleresult, @subtitleresult, @wordresult );
    my $searchtext = GetParam( 'search', '' );
    $searchtext =~ s/"//g;    # Strip off quotes, dunno why they're needed

    print GetHeader( '', T( 'Search Result' ) );
    print $q->p( { -class => 'subtitle' },
                 'Keyword used: <strong>' . $searchtext . '</strong>' );
    print $q->start_div( { -class => 'content metasearch' } );

    my $searchresult = OddMuse::Searching->new( $searchtext );

    for my $pages ( keys %{ $searchresult } ) {
        if ( $searchresult->{ $pages }{ 'type' } eq 'result_name' ) {
            push( @uriresult,
                  &renderSearchItem($searchtext,
                                    $searchresult->{ $pages }{ 'wikiname' },
                                    $searchresult->{ $pages }{ 'title' },
                                    $searchresult->{ $pages }{ 'subtitle' },
                                    $searchresult->{ $pages }{ 'recentauthor' },
                                    $searchresult->{ $pages }{ 'recentedit' },
                                    $searchresult->{ $pages }{ 'pagesize' },
                                    $searchresult->{ $pages }{ 'first' }
                                   )
                );
            $resultcount++;
        } ## end if ( $searchresult->{ ...
    } ## end for my $pages ( keys %{...

    for my $pages ( keys %{ $searchresult } ) {
        if ( $searchresult->{ $pages }{ 'type' } eq 'result_title' ) {
            push( @titleresult,
                  &renderSearchItem($searchtext,
                                    $searchresult->{ $pages }{ 'wikiname' },
                                    $searchresult->{ $pages }{ 'title' },
                                    $searchresult->{ $pages }{ 'subtitle' },
                                    $searchresult->{ $pages }{ 'recentauthor' },
                                    $searchresult->{ $pages }{ 'recentedit' },
                                    $searchresult->{ $pages }{ 'pagesize' },
                                    $searchresult->{ $pages }{ 'first' }
                                   )
                );
            $resultcount++;
        } ## end if ( $searchresult->{ ...
    } ## end for my $pages ( keys %{...

    for my $pages ( keys %{ $searchresult } ) {
        if ( $searchresult->{ $pages }{ 'type' } eq 'result_subtitle' ) {
            push( @subtitleresult,
                  &renderSearchItem($searchtext,
                                    $searchresult->{ $pages }{ 'wikiname' },
                                    $searchresult->{ $pages }{ 'title' },
                                    $searchresult->{ $pages }{ 'subtitle' },
                                    $searchresult->{ $pages }{ 'recentauthor' },
                                    $searchresult->{ $pages }{ 'recentedit' },
                                    $searchresult->{ $pages }{ 'pagesize' },
                                    $searchresult->{ $pages }{ 'first' }
                                   )
                );
            $resultcount++;
        } ## end if ( $searchresult->{ ...
    } ## end for my $pages ( keys %{...

    for my $pages ( keys %{ $searchresult } ) {
        if ( $searchresult->{ $pages }{ 'type' } eq 'result_words' ) {
            push( @wordresult,
                  &renderSearchItem($searchtext,
                                    $searchresult->{ $pages }{ 'wikiname' },
                                    $searchresult->{ $pages }{ 'title' },
                                    $searchresult->{ $pages }{ 'subtitle' },
                                    $searchresult->{ $pages }{ 'recentauthor' },
                                    $searchresult->{ $pages }{ 'recentedit' },
                                    $searchresult->{ $pages }{ 'pagesize' },
                                    $searchresult->{ $pages }{ 'first' }
                                   )
                );
            $resultcount++;
        } ## end if ( $searchresult->{ ...
    } ## end for my $pages ( keys %{...

    my $uricount      = scalar( @uriresult );
    my $titlecount    = scalar( @titleresult );
    my $subtitlecount = scalar( @subtitleresult );
    my $wordcount     = scalar( @wordresult );

    my ( @resultpara, @resultparapop );

    print "<p>";
    print 'There were ' . $resultcount . ' total matches of which ';

    push( @resultparapop, $uricount . ' were found in the page URI' )
      if $uricount;
    push( @resultparapop, $titlecount . ' were found in the page title' )
      if $titlecount;
    push( @resultparapop, $subtitlecount . ' were found in the page subtitle' )
      if $subtitlecount;
    push( @resultparapop, $wordcount . ' were found in the page content' )
      if $wordcount;

    my $temp = pop( @resultparapop );
    foreach my $resultpara ( @resultparapop ) {
        push( @resultpara, $resultpara . ", " );
    }
    push( @resultpara, " and " . $temp . "." );
    print @resultpara;
    print "</p>";

    print $q->h2( $uricount . ' results found in page URI ...' ) if $uricount;
    print $q->start_ol                                           if $uricount;
    print @uriresult                                             if $uricount;
    print $q->end_ol                                             if $uricount;

    print $q->h2( $titlecount . ' results found in page title ...' )
      if $titlecount;
    print $q->start_ol if $titlecount;
    print @titleresult if $titlecount;
    print $q->end_ol   if $titlecount;

    print $q->h2( $subtitlecount . ' results found in page subtitle ...' )
      if $subtitlecount;
    print $q->start_ol    if $subtitlecount;
    print @subtitleresult if $subtitlecount;
    print $q->end_ol      if $subtitlecount;

    print $q->h2( $wordcount . ' results found in page content ...' )
      if $wordcount;
    print $q->start_ol if $wordcount;
    print @wordresult  if $wordcount;
    print $q->end_ol   if $wordcount;

    if ( !$resultcount ) {
        print $q->p( 'Sorry, your search did not return any results.' );
        print $q->p(
            'Try removing any extra (and un-necessary) verbage from your search query.'
        );

    }

    my $searchgoogle = $searchtext;
    $searchgoogle =~ s/\ /\+/g;
    print $q->p(
        'This search engine searches for <strong><em>exact</em></strong> results.  This behavior is similar to how google would respond if you surrounded your search term in quotes.'
    );
    print $q->h2( 'Other Options' );

    print "<ul>";
    print
      '<li> Browse the <a href="/?action=printable-index" title="All that is good">Site Index</a></li>';
    my @queries = split( /\ /, $searchtext );
    if ( @queries ge 2 ) {
        print "<li>Re-run search on a single element, eg: ";
        $temp = pop( @queries );
        foreach my $query ( @queries ) {
            print ' '
              . GetSearchLink( $query, '', '',
                               T( 'Search for "' . $query . '"' ) )
              . ', ';
        }
        print ' '
          . GetSearchLink( $temp, '', '', T( 'Search for "' . $temp . '"' ) )
          . '.';
    } ## end if ( @queries ge 2 )

    print '<li> Search for "'
      . GetInterLink( 'Google:' . $searchgoogle, $searchtext, 0, 0 )
      . '" on Google</li>';
    print "</ul>";

    my @nearlinks = MetaSearchNearPages( $searchtext );

    if ( @nearlinks ) {
        print $q->h2( 'Similar Links on other Wikis' );
        print "<p>";
        my $temp = pop( @nearlinks );
        foreach my $link ( @nearlinks ) {
            my ( $class, $resolved, $title, $exists ) = ResolveId( $link );
            print $q->a( {  -href  => $resolved,
                            -class => $class,
                            -title => 'On ' . $title . 'Wiki : ' . $temp
                         },
                         $link
                       ) . ', ';
        } ## end foreach my $link ( @nearlinks)
        my ( $class, $resolved, $title, $exists ) = ResolveId( $temp );
        print ' '
          . $q->a( {  -href  => $resolved,
                      -class => $class,
                      -title => 'On ' . $title . 'Wiki : ' . $temp
                   },
                   $temp
                 );
        print "</p>";

    } ## end if ( @nearlinks )

    print $q->end_div;
    PrintFooter();

} ## end sub MetaSearch

=item * renderSearchItem

This function tests for a couple of conditions in the search result itself, and
returns a string containing the html to print.  For example, if there is no summary
text indexed, it excludes it from printing for cleaner looking results.

=cut

sub renderSearchItem {
    my ( $searchterm, $wikiname, $title, $subtitle, $recentauthor, $recentedit,
         $pagesize, $first )
      = @_;
    my ( $subtitleor, $infoblurb, $summary );

    $subtitleor = '<strong><em> or </em></strong>' . $subtitle if $subtitle;
    $summary = '<p>' . SearchHighlight( $first, $searchterm ) . "</p>"
      if ( $first !~ /^\ \.\.\./ );

    $infoblurb =
        '<span class="info"> Last edited '
      . &OddMuse::Date::LongTimeSince( $recentedit )
      . ' ago by '
      . GetPageOrEditLink( $recentauthor, unCamel( $recentauthor ) )
      . ', size: '
      . $pagesize
      . ' bytes</span>';

    if ( $title ) {
      return
          $q->li( { -class => 'search' },
                  ScriptLink( UrlEncode( $wikiname ), $title,
                              'local',                undef,
                              T( 'Internal Page: ' . $title )
                            ),
                  $subtitleor . $q->p( $summary ) . $q->p( $infoblurb )
                );
    } else {
      return
          $q->li( { -class => 'search' },
                  ScriptLink( UrlEncode( $wikiname ), $wikiname,
                              'local',                undef,
                              T( 'Internal Page: ' . $wikiname )
                            ),
                  $subtitleor . $q->p( $summary ) . $q->p( $infoblurb )
                );
    } ## end else [ if ( $title )
} ## end sub renderSearchItem

=item * MetaSearchNearPages

This function is a stripped down version of SearchNearPages function found in the
OddMuse wiki code.  It basicly prints more formatted list of the same data, in the
same spirit of the backlinks module.

=cut

sub MetaSearchNearPages {
    my $string = shift;
    my %found  = map { $_ => 1 } @_;
    my $regex  = HighlightRegex( $string );
    if ( %NearSource
         and ( GetParam( 'near', 1 ) or GetParam( 'context', 1 ) == 0 ) )
    {
        my $intro = 0;
        foreach my $name ( sort keys %NearSource ) {
          next if $found{ $name };    # do not duplicate local pages
            if ( SearchString( $string, NormalToFree( $name ) ) ) {
                $found{ $name } = 1;
                $intro = 1;
            }
        }
    } ## end if ( %NearSource and (...
  return keys( %found );
} ## end sub MetaSearchNearPages

1;

__END__

=back

=head1 BUGS AND LIMITATIONS

No bugs have been reported.

Please report any bugs or feature requests to C<cmauch@gmail.com>

=head1 AUTHOR

Charles Mauch <cmauch@gmail.com>

=head1 LICENSE

Copyright (c) 2006 Charles Mauch

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.  See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
Street, Fifth Floor, Boston, MA  02110-1301, USA.

=head1 SEE ALSO

perl(1).

=cut

# $Id: Engine.pm 30 2006-09-29 06:19:20Z cmauch $

